/*
-----------------------------------------------------------------------------
This source file is part of Labor3D
(Labor 3D Graphics Engine)

Copyright (c) 2011-2020 Rock Mao
* creator : Rock Mao
* created : 2011-5-2   22:29
* filename: LaborD3D11RenderSystem.h
-----------------------------------------------------------------------------
*/
#ifndef __LABORD3D11RENDERSYSTEM_H__
#define __LABORD3D11RENDERSYSTEM_H__

#include "LaborD3D11Def.h"
#include "LaborD3D11Device.h"
#include "Common/LaborObjectDepot.h"
#include "LaborD3D11InputLayout.h"
#include "LaborD3D11GPUProgram.h"
NAMESPACE_LABOR3D_BEGIN

class CLD3D112DRectRO;


struct sLD3D112DEnv
{
public:
	CLMatrix4x4 m_worldMatrix ;
	CLMatrix4x4 m_ViewMatrix;
	CLMatrix4x4 m_projectMatrix;

public:
	void convert();
};

class CLD3D11RenderSystem : public ILRenderSystem
{
private:
	CLD3D11Device                 m_Device;
	D3D_DRIVER_TYPE             m_driverType;
	IDXGISwapChain*               m_pSwapChain;
	ID3D11RenderTargetView* m_pRenderTargetView;
	ID3D11InputLayout*          m_pVertexLayout;
	ID3D11Buffer*                   m_pVertexBuffer;

	HINSTANCE               m_hInst;

	HWND                    m_hRenderWnd;
	sLD3D112DEnv            m_2DEnv;
private:
	ID3D11InputLayout*                  m_pCurrentVertexLayout;
	wstring                             m_strShaderPath;
	wstring                             m_strTexturePath;

	///-----   2D Object-------------------------------------------------------------------------
	CLD3D112DRectRO *                   m_pDefault2DRectRO;

	///-----  2d Object--------------------------------------------------------------------------

	CLD3D11GPUProgram *                 m_pGpuProgram;
private:
	//// inputlayout object manager
	TLObjectDepot<CLD3D11InputLayout> m_InputLayoutMgr;
	CLD3D11InputLayout*               m_pCurInputLayout;

public:
	CLD3D11RenderSystem(HINSTANCE hInstance);
	~CLD3D11RenderSystem();
	void*                   getInst() {return m_hInst; }
	virtual void            destroy();
	virtual const CLString& getName(void) const;
	
	// Viewport methods
	virtual void          setViewport( int x, int y, int width, int height );
	virtual void          getViewport( int& x, int& y, int& width, int& height ) const;
	virtual float         getViewportPixelWidth() const ;
	virtual float         getViewportPixelHeight() const ;

	virtual bool          initDevice(  int hWnd );
	virtual bool          cleanUpDevice();

	virtual void          clearBackBuffer( float r, float g, float b, float a );
	virtual void          present( int x, int y );
	virtual void          drawIndexed( int indexCount, int indexStart, int baseVertex );

	///@down for buffer
	virtual CLVertexBuffer*    createVertexBuffer(size_t vertexSize, size_t numVerts, EHB_Usage usage, bool useShadowBuffer = false);
	virtual CLIndexBuffer*     createIndexBuffer(eLIndexType itype, size_t numIndexes,EHB_Usage usage, bool useShadowBuffer = false);
	virtual CLConstantBuffer*  createConstantBuffer(size_t buffer_size);
	virtual ILSamplerState*    createSamplerState( const wchar_t * _name );
	virtual ILSamplerState*    createSamplerState( const sLSamplerStateDesc & _desc );
	virtual ILShader*          createShader(const wchar_t* shaderName , eLShaderType type);

	virtual void setVertexBuffer(UINT nStart, UINT nNumberBuffers, CLVertexBuffer *vBuffer, const UINT *pStrides, const UINT *pOffsets);
	virtual void setIndexBuffer( CLIndexBuffer *pBuffer,eLIndexType eIdxType, UINT Offset = 0);
	virtual void setPrimitiveTopology( eLPrimitiveTopology ePrimitiveTopology);
	virtual bool setSamplerState(int nSlot, ILSamplerState *pSamplerState);

	///@up for buffer
	/// @ input layout 
	virtual ILInputLayout*     createInputLayout(const wchar_t* name , CLInputLayoutDesc& desc);
	virtual bool setInputLayout( const wchar_t *pLayout );
	virtual bool setInputLayout( ILInputLayout* pInputLayout);

	TLObjectDepot<CLD3D11InputLayout> &getInputLayoutMgr() { return m_InputLayoutMgr; } 
	virtual ILInputLayout* getCurInputLayout();
	virtual ILInputLayout* getInputLayout( const wchar_t * layout_name);
	/// @
	virtual void begin();
	virtual void end();
	virtual void begin2D( int width = 0, int height = 0 );
	virtual void beginPerspective2D( float zValue = 1000.0f, int width = 0, int height = 0);
	virtual void end2D();
	///@ GPU program
	virtual bool setVertexShader( ILShader *pVertexShader );
	virtual bool setPixelShader( ILShader *pPixelShader);
	virtual bool setGeometryShader(ILShader *pGeomShader);

	virtual ILGpuProgram* createGPUProgram();
	virtual bool setGPUProgram(ILGpuProgram* pGpuProgram);

	/// set matrix
	void         setWorldMatrix(float* _World);
	void         setViewMatrix(float* _View);
	void         setProMatrix(float* _Pro);

	void  setWorldMatrix(CLMatrix4x4& _matWorld);
	void  setViewMatrix(CLMatrix4x4& _matView);
	void  setProMatrix(CLMatrix4x4& _matPro);

	/// temp

	virtual void *getDevice();
	ID3D11Device *D3D11Device();
	virtual void  setShaderPath( const wchar_t * strPath ) {  m_strShaderPath  = strPath; }
	virtual void  setTexturePath( const wchar_t * strPath ) { m_strTexturePath = strPath; }
	

	void freeMem(ID3D11ShaderResourceView* pTexture , float scale = 1.0f);
	void useMem(ID3D11ShaderResourceView* pTexture, float scale = 1.0f);

	virtual void setTexture( CLTexture *pTexture, int layer = 0 );
	CLTexture *  createTextureFromFile( const wchar_t * filename );

	virtual void drawRect( CLTexture *pTexture, CLRectF & destRect, CLRectF & srcRect, CLColor_4f& _color );
	virtual void drawRect( CLTexture *pTexture, CLRectF & destRect, CLColor_4f& _color );

	//----
	void         getCanvasSize(int& w , int & h);


private:
	void __initDefaultShader();
	bool __imlSetInputLayout( CLD3D11InputLayout *pLayout );
	bool __setup2DMatrix();
	bool __unSetup2DMatrix();
	bool __initInlineInputLayout();
};
NAMESPACE_LABOR3D_END
#endif // __LABORD3D11RENDERSYSTEM_H__
